using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace PhotoBlenderLib
{
	/// <summary>
	/// Summary description for Blender.
	/// </summary>
	public class Blender {

		#region private fields

		PhotoCollection photos;
		string outPath = string.Empty;
		int tHeight = 500;
		int tWidth = 500;
		Graphics gfx;
		Bitmap bitmap;

		#endregion


		/// <summary>
		/// Blender constructor
		/// </summary>
		/// <param name="paths"></param>
		public Blender(List<string> paths) {
			photos = PhotoFactory.CreatePhotoCollection(paths);
			SetOutputPath();
		}

		/// <summary>
		/// Blender Constructor
		/// </summary>
		/// <param name="paths"></param>
		/// <param name="targetHeight"></param>
		/// <param name="targetWidth"></param>
		public Blender(List<string> paths, int targetWidth, int targetHeight, string outputPath) {
			photos = PhotoFactory.CreatePhotoCollection(paths);
			tHeight = targetHeight;
			tWidth = targetWidth;
            outPath = outputPath;
			SetOutputPath();
		}


		/// <summary>
		/// Set output path
		/// </summary>
		private void SetOutputPath() {
            //outPath = ConfigurationManager.AppSettings["filepath"];
			if(outPath != null && outPath.EndsWith(@"\")) {
				outPath = outPath.Substring(0, outPath.Length - 1);
			}
			if(!Directory.Exists(outPath))
				throw new FileNotFoundException("File not found.", outPath);
		}


		/// <summary>
		/// Blend photos
		/// </summary>
		/// <param name="a"></param>
		public void BlendPhotos() {

			// set up graphics
			InitializeGraphics();

			Rectangle targetRect;
			PixelStorage px = new PixelStorage(bitmap.Width, bitmap.Height);
			
			for(int i = 0; i < photos.Count; i++) {
				Bitmap bmp = photos[i].Image;
				
				gfx.Clear(Color.Black);

				// setup target rectangle
				targetRect = GetTargetRectangle(tWidth, tHeight, bmp.Width, bmp.Height);
				
				// draw the photo on our graphics object
				gfx.DrawImage(bmp, targetRect, new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);

                // add the image to the average
                px.AddAverage(bitmap);

				photos[i].Dispose();
			}
			bitmap = px.GetAveragePhoto();
			bitmap.Save(outPath + @"\Output.jpg");
			
		}



		private void InitializeGraphics() {
			// setup the bitmap
			bitmap = new Bitmap(tWidth, tHeight);

			// Setup the graphics object
			gfx = Graphics.FromImage(bitmap);
			gfx.Clear(Color.Black);
			gfx.CompositingMode = CompositingMode.SourceOver;
		}


		private Rectangle GetTargetRectangle(int targetWidth, int targetHeight, int sourceWidth, int sourceHeight) {
			
			double phi = (1 + Math.Sqrt(5)) / 2;
			double standardArea = targetWidth * (targetWidth / phi);
    
			// resize here to all occupy about the same area on screen.
			int area = sourceWidth * sourceHeight;
			double factor = Math.Sqrt( standardArea * 1.0d / (double)area );
			sourceWidth = (int)((double)sourceWidth * factor);
			sourceHeight = (int)((double)sourceHeight * factor);
        
			// but stay within the maximum screen.
			if (sourceWidth > targetWidth || sourceHeight > targetHeight) {
				if (sourceWidth > sourceHeight) {
					// landscape
					sourceWidth = targetWidth;
					sourceHeight *= (int)((double)targetWidth / (double)sourceWidth);
				} else {   
					// portrait
					sourceWidth *= (int)((double)targetHeight / (double)sourceHeight);
					sourceHeight = targetHeight;
				}
			}

			Size size = new Size();
			size.Width = sourceWidth;
			size.Height = sourceHeight;

			Point origin = new Point();
			origin.X = (targetWidth - sourceWidth) / 2;
			origin.Y = (targetHeight - sourceHeight) / 2;
			
			Rectangle rect = new Rectangle(origin, size);
			return rect;
		}

		
	}
}
